package com.example.weatherdemotest;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatSpinner;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.example.weatherdemotest.adapter.FutureWeatherAdapter;
import com.example.weatherdemotest.bean.DayWeatherBean;
import com.example.weatherdemotest.bean.WeatherBean;
import com.example.weatherdemotest.location.LocationCallback;
import com.example.weatherdemotest.location.MyLocationListener;
import com.example.weatherdemotest.util.NetUtil;
import com.google.gson.Gson;

import java.util.List;

public class MainActivity extends AppCompatActivity implements LocationCallback {
    private AppCompatSpinner mSpinner; //实例化spinner
    private ArrayAdapter<String> mSpAdapter; //spinner的Adapter
    private String[] mCities; //spinner的数据源

    //以下三行为当前所选城市的天气情况控件实例化
    private TextView tvWeatherContent, tvTemperature, tvWind, tvLowHigh, tvSelectedCity;
    private ImageView ivWeatherIcon;
    private RecyclerView rlvFutureWeather;

    //以下为显示未来七天内天气情况
    private FutureWeatherAdapter mFutureWeatherAdapter;

    //2023-03-23
    // 以下两行为百度地图定位
    public LocationClient mLocationClient = null;
    private final MyLocationListener myListener = new MyLocationListener();
    public static String LocCity;
    //2023-03-23权限数组
    private final String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    //2023-03-23请求权限意图
    private ActivityResultLauncher<String[]> requestPermissionIntent;


    //将获取到的 所选城市的 天气情况 返回给主线程
    private Handler mHandler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                //108行
                //1、此时获得的weather是一个需要解析的json格式
                String weather = (String) msg.obj;
                Log.d("SUN", "---SELECTED_WEATHER------in_main_thread---" + weather);

                //2、将获取的weather(json对象) 进行解析
                Gson gson = new Gson();
                WeatherBean weatherBean = gson.fromJson(weather, WeatherBean.class); //将weather解析成WeatherBean这个格式
                Log.d("SUN", "---WEATHER_BEAN---" + weatherBean.toString());

                //3、更新控件
                updateUiOfWeather(weatherBean);

            }
        }
    };


    /**
     * 根据获取和处理后的网络数据，更新UI控件的显示内容
     */
    private void updateUiOfWeather(WeatherBean weatherBean) {
        //1、首先判断数据是否为空，为空则出现异常
        if (weatherBean == null) {
            return;
        }

        //2、数据不为空，获取数据信息
        //2.1 拿到当天的数据dayWeathers
        List<DayWeatherBean> dayWeathers = weatherBean.getDayWeathers();
        DayWeatherBean todayWeather = dayWeathers.get(0); //dayWeathers.get(0)为当天数据的详细信息
        if (todayWeather == null) {
            return;
        }

        //2.2 将当天的数据更新到控件上
        tvSelectedCity.setText(weatherBean.getCity());
        ivWeatherIcon.setImageResource(getWeatherIcon(todayWeather.getWeatherIcon())); //天气图标
        tvTemperature.setText(todayWeather.getWeatherTemDay() + "°C");  //16°C
        tvWeatherContent.setText(todayWeather.getWeather() + "(" + todayWeather.getDate() + ")"); //晴(2023-03-20)
        tvLowHigh.setText(todayWeather.getWeatherTemNight() + "°C ~" + todayWeather.getWeatherTemDay() + "°C"); //7°C~12°C
        tvWind.setText(todayWeather.getWind() + " " + todayWeather.getWindspeed()); //东南风 <3级
        //tvAir无可获取信息，暂时不设置

        //设置actionBar的text
        setActionBar(weatherBean);


        //3、将未来的天气情况显示到RecyclerView上
        //2.1的dayWeathers.get(0) 为当前天气情况 传入Adapter的为删除第一天后剩下的天气情况
        //3.1 首先删除第一个数据，剩下的即为需要在RecyclerView展示的未来的天气情况
        dayWeathers.remove(0);
        //3.2 将剩余的天气情况传入Adapter
        mFutureWeatherAdapter = new FutureWeatherAdapter(this, dayWeathers);
        //3.3 将Adapter设置到RecyclerView中
        rlvFutureWeather.setAdapter(mFutureWeatherAdapter);
        //3.4 为RecyclerView设置显示样式，采用水平方向上的线性布局显示
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        rlvFutureWeather.setLayoutManager(linearLayoutManager);
        //3.5 为RecyclerView设置显示样式，每个item之间留有一定的间隙，便于显示
        rlvFutureWeather.addItemDecoration(new MyRlcDuration());
    }

    /**
     * 2023-03-23
     * 初始化定位
     */
    private void initLocation() {
        try {
            mLocationClient = new LocationClient(getApplicationContext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (mLocationClient != null) {
            myListener.setCallback(this);
            //注册定位监听
            mLocationClient.registerLocationListener(myListener);
            LocationClientOption option = new LocationClientOption();
            //如果开发者需要获得当前点的地址信息，此处必须为true
            option.setIsNeedAddress(true);
            //可选，设置是否需要最新版本的地址信息。默认不需要，即参数为false
            option.setNeedNewVersionRgc(true);
            //需将配置好的LocationClientOption对象，通过setLocOption方法传递给LocationClient对象使用
            mLocationClient.setLocOption(option);
        }
    }

    /**
     * 2023-03-23
     *
     * @param bdLocation 定位数据
     */
    @Override
    public void onReceiveLocation(BDLocation bdLocation) {
        double latitude = bdLocation.getLatitude(); //获取纬度信息
        double longtitude = bdLocation.getLongitude();  //获取经度信息
        float radius = bdLocation.getRadius();    //获取定位精度，默认值为0.0f
        String coorType = bdLocation.getCoorType();
        //获取经纬度坐标类型，以LocationClientOption中设置过的坐标类型为准
        int errorCode = bdLocation.getLocType();//161  表示网络定位结果
        //获取定位类型、定位错误返回码，具体信息可参照类参考中BDLocation类中的说明
        String addr = bdLocation.getAddrStr();    //获取详细地址信息
        String country = bdLocation.getCountry();    //获取国家
        String province = bdLocation.getProvince();    //获取省份
        String city = bdLocation.getCity();    //获取城市
        String district = bdLocation.getDistrict();    //获取区县
        String street = bdLocation.getStreet();    //获取街道信息
        String locationDescribe = bdLocation.getLocationDescribe();    //获取位置描述信息


        LocCity = city.substring(0, city.length() - 1); //为首页显示当前城市天气情况做准备
        Log.d("SUN", "---location_city---" + LocCity);
    }

    /**
     * 2023-03-23
     * 启动位置定位
     */
    private void startLocation() {
        if (mLocationClient != null) {
            mLocationClient.start();
        }
    }

    /**
     * 2023-03-23
     * 通过意图的方式动态请求多个权限
     */
    private void registerIntent() {
        //请求权限意图
        requestPermissionIntent = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
            boolean fineLocation = Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_FINE_LOCATION));
            boolean writeStorage = Boolean.TRUE.equals(result.get(Manifest.permission.WRITE_EXTERNAL_STORAGE));
            if (fineLocation && writeStorage) {
                //权限已经获取到，开始定位
                startLocation();
            }
        });
    }


    /**
     * 为RecyclerView的每一项添加空隙，实现padding效果
     */
    class MyRlcDuration extends RecyclerView.ItemDecoration {
        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.bottom = 25;
        }
    }

    /**
     * 根据返回的天气情况设置不同的天气图标
     * 固定9种类型(您也可以根据wea字段自己处理):
     * *      xue(icon_weather_daxue)、
     * *      lei(icon_weather_leiyu)、
     * *      shachen(icon_weather_shachen)、
     * *      wu(icon_weather_wumai)、
     * *      bingbao(icon_weather_bingbao)、
     * *      yun(icon_weather_duoyun)、
     * *      yu(icon_weather_zhongyu)、
     * *      yin(icon_weather_yin)、
     * *      qing(icon_weather_qing)
     *
     * @param weaStr
     * @return
     */
    private int getWeatherIcon(String weaStr) {
        int result = 0;
        switch (weaStr) {
            case "xue":
                result = R.drawable.icon_weather_daxue;
                break;
            case "lei":
                result = R.drawable.icon_weather_leiyu;
                break;
            case "shachen":
                result = R.drawable.icon_weather_shachen;
                break;
            case "wu":
                result = R.drawable.icon_weather_wumai;
                break;
            case "bingbao":
                result = R.drawable.icon_weather_bingbao;
                break;
            case "yun":
                result = R.drawable.icon_weather_duoyun;
                break;
            case "yu":
                result = R.drawable.icon_weather_zhongyu;
                break;
            case "yin":
                result = R.drawable.icon_weather_yin;
                break;
            case "qing":
                result = R.drawable.icon_weather_qing;
                break;
            default:
                result = R.drawable.icon_weather_loading;
                break;
        }
        return result;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //2023-03-23 新加的意图需要在Activity初始化之前进行注册
        registerIntent();

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //显示自定义Spinner
        initView();

        //2023-03-23
        initLocation();
        requestPermission();

    }

    /**
     * 2023-03-23
     * 请求权限
     */
    private void requestPermission() {
        //因为项目的最低版本API是23，所以肯定需要动态请求危险权限，只需要判断权限是否拥有即可
        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            //开始权限请求
            requestPermissionIntent.launch(permissions);
            return;
        }
        //开始定位
        startLocation();
    }

    /**
     * Spinner下拉选项框的初始化
     * 选项框的每一项采用自定义视图R.layout.spinner_item_layout
     * 数据源为strings.xml中添加的34个省会城市R.array.cities
     */
    private void initView() {
        mSpinner = (AppCompatSpinner) findViewById(R.id.spinner_cities);
        mCities = getResources().getStringArray(R.array.cities);
        mSpAdapter = new ArrayAdapter<>(this, R.layout.spinner_item_layout, mCities);
        mSpinner.setAdapter(mSpAdapter);

        //为spinner添加Item点击事件
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
                //1、拿到选中的位置城市
                String selectedCity = mCities[position];
                //2、获取选中城市的天气情况
                getWeatherOfCity(selectedCity);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        //所要用到的控件的初始化和绑定
        tvSelectedCity = (TextView) findViewById(R.id.tv_selected_city);
        ivWeatherIcon = (ImageView) findViewById(R.id.iv_weather_icon);

        tvTemperature = (TextView) findViewById(R.id.tv_weather_temperature);
        tvWeatherContent = (TextView) findViewById(R.id.tv_weather_content);
        tvLowHigh = (TextView) findViewById(R.id.tv_weather_low_high);
        tvWind = (TextView) findViewById(R.id.tv_weather_wind);

        rlvFutureWeather = (RecyclerView) findViewById(R.id.rlv_future_weather);
    }

    /**
     * 涉及Android内容:
     * 1、开启子线程，请求网络
     * 2、Android网络请求中的Get与Post方法
     * <p>
     * 功能：
     * 通过url获取选中城市未来七天的天气情况
     *
     * @param selectedCity
     */
    private void getWeatherOfCity(String selectedCity) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //1、请求网络
                String weatherOfCity = NetUtil.getWeatherOfCity(selectedCity);

                //2、使用Handler将数据传递给主线程
                Message message = Message.obtain();
                message.what = 0;//消息标号(id)
                message.obj = weatherOfCity; //携带的数据在这里

                mHandler.sendMessage(message);
            }
        }).start();
    }

    /**
     * 增加ActionBar的menu
     *
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_setting, menu); //绑定菜单布局
        return true;
    }

    /**
     * 添加menu的点击事件，转至系统设置
     *
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        startActivity(intent);
        return true;
    }

    /**
     * 将ActionBar设为透明
     * 1、首先让整个页面全屏显示
     * 对于SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, 设置fitsSystemWindows="true"的view会被系统自动添加大小为statusBar和ActionBar高度之和相同的paddingTop
     *
     * @param hasFocus
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN   //在不隐藏StatusBar的情况下，将view所在window的显示范围扩展到StatusBar下面。同时Activity的部分内容也因此被StatusBar覆盖遮挡
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;   //作用: 稳定布局
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
            //设置状态栏为透明色
        }
    }

    /**
     * 将ActionBar设为透明
     * 2、设置actionBar的文字和效果
     *
     * @param weatherBean
     */
    private void setActionBar(WeatherBean weatherBean) {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#00000000")));
        actionBar.setSplitBackgroundDrawable(new ColorDrawable(Color.parseColor("#00000000")));
        actionBar.setTitle(weatherBean.getCity()); //updateUiOfWeather()中添加对actionBar文字的修改
    }
}